﻿#ifndef _COM_SERIAL_H__
#define _COM_SERIAL_H__
#include "protocol/codec.h"
#include "protocol/command.h"
#include "utils/findcomputercom.h"
#include "serial/qextserialport.h"
#include <QQueue>
#include <QThread>

class Serial;
class CQueue{
public:
    CQueue() {

    }
    void enqueue(Command *data);
    void enqueue_tail(Command *data);
    Command *dequeue();
    bool is_empty(){
        return Head.next == &Head;
    }
    Command *head(){
        return &Head;
    }
    void removeOne(Command *command);
    void removeOneLocked(Command *c);
    void lockqueue(){
        lock.lock();
    }
    void unlockqueue(){
        lock.unlock();
    }
    ~CQueue() {
        Command *temp, *node;
        lockqueue();
        for (node = head()->next, temp = node->next; node != head(); node=temp, temp=node->next) {
            removeOneLocked(node);
            delete node;
        }
        unlockqueue();

    }
private:
    Command Head;
    QMutex lock;
    QWaitCondition Cond;
};

class Serial:public QObject{
    Q_OBJECT
public:
    explicit Serial();
    ~Serial() {
        disconnect(this, SLOT(onRecvCommand));
        disconnect(this, SLOT(readPort()));
    }
    QStringList GethwPorts();
    bool OpenPort(QString name, int band, bool direct = true);
    void ClosePort();
    void Send(Command *c, bool just_wait = false);
    void DirectConnect(bool direct);
    bool OpenPortInt();
    void ClosePortInt();
signals:
    void frameReady(RxMessage &);//完整帧信号，主要给异步调用者使用
    void portStatusChanged(bool opened);
    void sendFrame();
    void openPort();
    void closePort();
public slots:
    void onRecvFrame(QByteArray &frame);
    void onRecvPackage(RxMessage *message);
    void readPort();
    void about_close();
    void writePort();
    void onTimerOut();
//protected:
//    void run() override;
private:
    void onResendTimeOut();
    Decoder *decoder;
    QMap<int, RxMessage*> rx_messages;
    QextSerialPort *port;
    bool        b_direct;
    QTimer *timer;
    QThread *worker;
    QString com_name;
    int band_rate;
    bool direction;
    CQueue queue;
    CQueue wait_queue;
    volatile bool b_serial_open;
};

extern int serial_max_frame_size;

#endif /* _COM_SERIAL_H__ */
